Schneider IGSS远程溢出漏洞分析
更多安全资讯和分析文章请关注启明星辰ADLab微信公众号及官方网站(adlab.venustech.com.cn)
前言
近期,启明星辰ADLab对Schneider SCADA(Interactive Graphical SCADA System,简称IGSS)的漏洞补丁进行了深入分析,发现这些补丁并没有从根源上修复多个高危缓冲区溢出漏洞,导致IGSS仍可以被远程溢出。ADLab研究员对这些高危漏洞进行了详细分析和实际验证,并及时协助厂商进行了修复。
漏洞基本信息
根据schneider的漏洞公告[1],这些高危漏洞的基本信息如下:
受影响的产品:V15.0.0.22170 and prior
CVE-2022-32522,缓冲区溢出 CVE-2022-32523,缓冲区溢出 CVE-2022-32524,缓冲区溢出 CVE-2022-32525,缓冲区溢出 CVE-2022-32526,缓冲区溢出 CVE-2022-32527,缓冲区溢出 CVE-2022-32529,缓冲区溢出
漏洞分析与验证
3.1 报文处理过程
第一个红框中,传入sub_4B3090的第一个参数 a1为一个中间缓存区,用来存放IGSS在执行具体功能过程中产生的中间量;第二个参数 1则是该函数的状态量。sub_4B3090内部是一个嵌套式的switch结构,根据输入的参数来决定具体的执行分支。
sub_4B3090函数如下图所示,程序最终会在此处通过WSARecv接收用户传入的数据:
结合上述代码分析,IGSS对接收数据的格式要求如下:
接收数据的大小不能大于0x1000 0 – 2字节的内容为数据的总长度 2 - 4字节的内容必须为1 6 - 10字节的内容为opcde(用于接下来的功能分支)
因此,通过网络只需要发送满足该格式的数据包后就可以请求IGSS执行相应代码。
3.2 初始漏洞分析
运行一个初始漏洞的POC,靶机IGSS崩溃,windbg给出如下崩溃信息:
通过IDA定位到崩溃点,位于程序的Request LOG功能的memcpy代码处,如下所示。
经过逆向分析得知,该处函数的作用是用于处理报文分片的拼接处理,即:在实际接收数据包的过程当中,若接收的数据包并不是一次发送完全,就会继续接收数据;每接收一次后续数据,就会调用该函数将新报文的内容拼接到现有报文的尾部。
分析报文的数据结构得知,该函数要处理的数据有如下图的结构:即18字节的头文件, 18字节的“数据块头”用来存储 “数据块”数量信息,最后是具体的数据块内容(每个数据块的大小为12字节):
预期的拼接逻辑如下,发送端发送了如下的两个数据包B1和B2 :
IGSS通过sub_4A6390进行如下操作:首先realloc申请了12*B2_len长度的缓冲区来扩展B1,接下来使用memcpy将B2数据块的内容拷贝在原B1数据的末尾。
但是,IGSS没有正确校验报文B1的数据结构,导致上文的初始漏洞POC触发了靶机IGSS的拼接漏洞,逻辑如下:
即第一次发送的数据包不存在数据块(B1_len = 0,B2_len = 1),当IGSS执行到sub_4A6390函数则会发生如下图所示情况:
其中,中间蓝色部分是realloc函数申请的12*B2_len长度的缓冲区,这里的B2_len设置成1也就是12字节,所以扩展后存放B1数据所申请的缓冲区大小为30(18+12)字节。经过分析,memcpy的参数*(v8+4)指向了B1缓冲区的开头,而*(*(v8+4)+18)指的是B1的B1_len的长度。由于B1_len = 0,所以memcpy第一个参数的值为:*(v8+4)+36。显然,*(v8+4)+36所指向的地址已经超出了B1缓冲区30字节,因此就造成非法地址写入,导致IGSS崩溃。
3.3 补丁绕过分析
为了修复此类漏洞,施耐德官方发布了V15.0.0.22082来进行修复,其核心是sub_4B40E0函数处,也就是上文所述在检验数据包头部的地方:
分析sub_4B8EE0可知,其是根据不同的opcode来限制每个数据包的长度,上述漏洞的opcode为1,进入case 1随后赋值48给v2之后将v2返回给上图中的v3,接下来判断v88[1051]是否小于v3,v88[1051]实际上存储的是数据包的长度,也就是说此处理论上规定了数据包的大小必须大于48字节(也就是18字节的数据包头部,18字节的数据块头部,加上至少1个数据块12字节的大小总共48字节)来限制上述因为不存在数据块而导致的溢出情况,否则程序会直接返回0:
打过补丁后,初始的漏洞POC就不再有效了。但是,通过对比分析数据拼接的逻辑和补丁代码,ADLab研究员发现初始补丁只是修复了初始POC对应的漏洞利用方式,并没有彻底修复漏洞。
3.4 最新补丁分析
启明星辰ADLab第一时间向施耐德报告了初始补丁绕过问题,官方在新版本(v15.0.0.22214)再次修复了该漏洞。经过分析,最新补丁彻底修复了这批漏洞。补丁存在于sub_4B42D0:
sub_4BA7E0的伪代码如下图所示。同样是按照Opcode选择分支,以case 1为例,不再像之前的版本一样将块的长度限制成最小48字节,而是限制成最小0xA3A字节的大小,也就是数据块的数量要求最少215(0xd7)个,最后将计算后的数据块大小返回赋值给上图红框中的v3,之后再与v88[1051]作比较,即整个数据包的长度最小要等于0xA3A,最新的补丁就限制了B1不能存在声明的数据块数量和实际数据包长度不匹配的情况:
还有一处补丁代码是限制Size(第二次发送数据包的数据块大小)不能大于4060字节,也就是每次发送数据包长度的最大值4096 -数据包头部和数据块头部总大小18+18(36)共4060字节,至此该漏洞被修复:
修复建议
经过ADLab研究员的分析和验证,上述高危漏洞都可以通过网络进行无条件的远程触发,具有很大的危害性。目前官方已经发布了补丁,强烈建议使用IGGS的工业用户立即升级版本到15.0.0.22171及以上。
针对工业控制系统,CISA提供了如下的通用建议:
尽量减少在公网暴露工控设备或者系统; 将控制系统网络和远程设备置于防火墙之后,并和办公网络隔离; 当需要远程访问时,采用类型VPN的安全访问方式。
参考链接:
启明星辰积极防御实验室(ADLab)
ADLab成立于1999年,是中国安全行业最早成立的攻防技术研究实验室之一,微软MAPP计划核心成员,“黑雀攻击”概念首推者。截止目前,ADLab已通过CVE累计发布安全漏洞近1100个,通过 CNVD/CNNVD累计发布安全漏洞2000余个,持续保持国际网络安全领域一流水准。实验室研究方向涵盖操作系统与应用系统安全研究、移动智能终端安全研究、物联网智能设备安全研究、Web安全研究、工控系统安全研究、云安全研究。研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等。